<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of LibUtil
 * @author dryoung
 */
class LibUtil
{

    /**
     * 发起http请求
     * @param string $url 访问路径
     * @param array $params 参数，该数组多于1个，表示为POST
     * @param int $expire 请求超时时间
     * @param array $extend 请求伪造包头参数
     * @param string $hostIp HOST的地址
     * @return array    返回的为一个请求状态，一个内容
     */
    public static function makeRequest($url, $params = array(), $expire = 0, $extend = array(), $hostIp = '')
    {
        if (empty($url)) {
            return array('code' => '100');
        }

        $_curl = curl_init();
        $_header = array(
            'Accept-Language: zh-CN',
            'Connection: Keep-Alive',
            'Cache-Control: no-cache'
        );
        // 方便直接访问要设置host的地址
        if (!empty($hostIp)) {
            $urlInfo = parse_url($url);
            if (empty($urlInfo['host'])) {
                $urlInfo['host'] = substr(DOMAIN, 7, -1);
                $url = "http://{$hostIp}{$url}";
            } else {
                $url = str_replace($urlInfo['host'], $hostIp, $url);
            }
            $_header[] = "Host: {$urlInfo['host']}";
            if (!empty($extend[CURLOPT_HTTPHEADER])) {
                $extend[CURLOPT_HTTPHEADER][] = "Host: {$urlInfo['host']}";
            }
        }

        // 只要第二个参数传了值之后，就是POST的
        if (!empty($params)) {
            curl_setopt($_curl, CURLOPT_POSTFIELDS, is_array($params) ? http_build_query($params) : $params);
            curl_setopt($_curl, CURLOPT_POST, true);
        }

        if (substr($url, 0, 8) == 'https://') {
            curl_setopt($_curl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($_curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        }

        curl_setopt($_curl, CURLOPT_URL, $url);
        curl_setopt($_curl, CURLOPT_RETURNTRANSFER, true);
        if (!isset($extend[CURLOPT_USERAGENT])) {
            curl_setopt($_curl, CURLOPT_USERAGENT, 'API PHP CURL (X-Real-IP:' . ip2long(self::getIp()) . ')');
        }
        if (empty($extend[CURLOPT_HTTPHEADER])) {
            curl_setopt($_curl, CURLOPT_HTTPHEADER, $_header);
        }

        if ($expire > 0) {
            curl_setopt($_curl, CURLOPT_TIMEOUT, $expire); // 处理超时时间
            curl_setopt($_curl, CURLOPT_CONNECTTIMEOUT, $expire); // 建立连接超时时间
        }

        // 额外的配置
        if (!empty($extend)) {
            curl_setopt_array($_curl, $extend);
        }

        $result['result'] = curl_exec($_curl);
        $result['code'] = curl_getinfo($_curl, CURLINFO_HTTP_CODE);
        $result['info'] = curl_getinfo($_curl);
        if ($result['result'] === false) {
            $result['result'] = curl_error($_curl);
            $result['code'] = -curl_errno($_curl);
        }

        /*
                PubSysLog::log('requestLog', array(
                    'url' => $url,
                    'data' => json_encode(PubUtil::forceUtf8($params)),
                    'info' => json_encode($result['info']),
                    'result' => strlen($result['result']) > 1024 ? "bigString" : $result['result']
                ));
        */

        curl_close($_curl);

        return $result;
    }

    /**
     * 取得真实IP
     * @param string $type
     * @return string
     */
    public static function getIp($type = 'REMOTE_ADDR')
    {
        // 我们机器的反向 优先用HTTP_X_REAL_IP
        $types = array('HTTP_X_REAL_IP', 'REMOTE_ADDR', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR');
        // 我们的代理IP
        $agentIp = array('127.0.0.1');
        if (in_array($_SERVER['REMOTE_ADDR'], $agentIp)) {
            preg_match('/\(X-Real-IP:(\d+)\)/', $_SERVER['HTTP_USER_AGENT'], $matches);
            if (!empty($matches)) {
                return long2ip($matches[1]);
            }
        }

        if (!empty($_SERVER['HTTP_X_REAL_IP']) && in_array($_SERVER['HTTP_X_REAL_IP'], $agentIp)) {
            $forward = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $_SERVER['HTTP_X_REAL_IP'] = trim($forward[count($forward) - 2]);
        }

        if (!in_array($type, $types)) {
            $type = $types[0];
        }

        do {
            $t = array_shift($types);
            $ip = empty($_SERVER[$t]) ? "" : $_SERVER[$t];

            if ($t == $type) {
                break;
            }
        } while (empty($ip) && !empty($types));
        $ip = explode(',', $ip);

        return $ip[0];
    }

    /**
     * cookie操作方法
     * 操作.xx.com下的根目录cookie的方法
     * @param string $name cookie名称
     * @param type $value 留空为取cookie,''为删除cookie
     * @param type $expire 留空则set一个session时效的cookie
     * @return mix $cookieValue
     */
    public static function cookie($name, $value = null, $expire = null, $domain = null)
    {
        if (!$name) {
            throw new LogicException('cookie调用参数错误');
        }
        // 留空为取cookie
        if ($value === null) {
            return isset($_COOKIE[$name]) ? $_COOKIE[$name] : false;
        }

        if (empty($domain)) {
            if (!empty($_SERVER['HTTP_ORIGIN'])) {
                //SERVER_NAME 在设置了反向代理的情况下不可用
                $urlInfo = parse_url($_SERVER['HTTP_ORIGIN']);
                $domain = strstr($urlInfo['host'], '.');
            } elseif (!empty($_SERVER['HTTP_HOST'])) {
                $_SERVER['HTTP_HOST'] = explode(':', $_SERVER['HTTP_HOST']);
                $domain = strstr($_SERVER['HTTP_HOST'][0], '.');
            }
        }
        // ''为清除cookie
        if ($value === '') {
            unset($_COOKIE[$name]);
            file_put_contents('/tmp/debugUser3.log', $name . "\t" . $domain . "\n", FILE_APPEND);
            return setcookie($name, "delete", time() - 1, '/', $domain);
        } // 写cookie
        else {
            if ($expire) {
                $expire += time();
            }

            $_COOKIE[$name] = $value;
            file_put_contents('/tmp/debugUser4.log', $name . "\t" . $domain . "\n", FILE_APPEND);
            return setcookie($name, $value, $expire, '/', $domain);
        }
    }


    /**
     * 处理session
     * @param string $key session的键值
     * @param mix $value session的值
     * @return mix
     */
    static function session($key, $value = null)
    {
        if (!isset($_SESSION)) {
            session_start();
        }
        if (isset($value)) {
            $_SESSION[$key] = $value;

            return true;
        } else {
            return isset($_SESSION[$key]) ? $_SESSION[$key] : '';
        }
    }

    /**
     * 取得次日0点的时间
     * @param type $time
     * @return type
     */
    static function getNextdayTime($time = '')
    {
        $time = (int)$time;
        if (!$time) {
            $time = time();
        }

        return strtotime(date("Y-m-d", strtotime('+1 day', $time)));
    }

    /**
     * 字符串命名风格转换
     * @param string name 字符串
     * @param int    type 转换类型 default：1
     *               =0 将Java风格转换为C的风格 UserModel=>user_model
     *               =1 将C风格转换为Java的风格 user_model=>UserModel
     *               =2 Java风格，但不转换首字母user_model=>userModel
     * @return string
     */
    static function parseName($name, $type = 1)
    {

        $name = preg_replace("/[A-Z]/", "_\\0", $name);

        return strtolower(trim($name, "_"));

    }

    /**
     * 参数替换
     * @param type $data
     * @param type $format
     * @return type
     */
    public static function replaceValue($data, $format)
    {
        if (preg_match('/^<\{\$(\w+)\|(\w+)\}>$/', $format, $matches)) {
            return self::replaceRun("\${$matches[1]}|{$matches[2]}", $data);
        }

        if (!empty($data['userName']) && strpos($data['userName'], '}') === false) {
            $pattern1 = '/<\{\$([^\|\}]*)\|?([^\}]*)?\}>/i';
        } else {
            $pattern1 = '/<\{\$([^\|\>]*)\|?([^\>]*)?\}>/i';
        }

        //$format = preg_replace_callback($pattern1, function ($r) use ($data) {
        //    return self::replaceRun("\${$r[1]}|{$r[2]}", $data);
        //}, $format);

        while (substr_count($format, '<{') > 0 && substr_count($format, '}>') > 0) {
            $_m = -1;
            for ($x = strpos($format, '<{'); $x < strlen($format); $x++) {
                if (substr($format, $x, 2) == '<{') {
                    $_m = $x;
                }

                if (substr($format, $x, 2) == '}>' && $_m >= 0) {
                    $code = substr($format, $_m + 2, $x - $_m - 2);
                    $format = substr($format, 0, $_m) . self::replaceRun($code, $data) . substr($format, $x + 2);
                    $_m = -1;
                }
            }
            //$format = preg_replace('/<{((.((?<!<{)[^|](?!}>))+.)(\|((.(?!}>))*.))?)}>/ei', '$5(\'$2\')', $format);
        }

        return $format;
    }

    private static $allowFunction = array();

    private static function replaceRun($code, $data = array())
    {
        if (empty($code)) {
            return '';
        }
        $code = explode('|', $code);
        if ($code[0][0] == '$') {
            $code[0] = !isset($data[substr($code[0], 1)]) ? "" : $data[substr($code[0], 1)];
        }
        if (empty($code[1])) {
            return $code[0];
        } else {
            $code[1] = explode(":", $code[1]);
            if (empty(self::$allowFunction)) {
                self::$allowFunction = load_config('replaceAllowFunctions');
            }
            if (empty(self::$allowFunction[$code[1][0]])) {
                return "{$code[1][0]} not allow";
            }
            if (!empty($code[1][1])) {
                $code[0] .= "','" . implode("','", explode(',', $code[1][1]));
            }
            $_s = '';
            if (function_exists($code[1][0])) {
                if (is_array($code[0])) {
                    $_s = $code[1][0]($code[0]);
                } else {
                    eval("\$_s = {$code[1][0]}('{$code[0]}');");
                }
            } else {
                eval("\$_s = self::{$code[1][0]}('{$code[0]}');");
            }

            return $_s;
        }
    }

    private static function modRun($data, $modName, $function, $extParameter)
    {
        if (strpos($modName, 'Mod') !== 0) {
            $modName = "Mod" . ucfirst($modName);
        }
        if (!is_file(PATH_MOD . "/{$modName}.php")) {
            return $data;
        }

        $mod = new $modName();
        if (empty($extParameter)) {
            return $mod->{$function}($data);
        } else {
            $_t = "";
            eval("\$_t = \$mod->{$function}('$data', '{$extParameter}');");

            return $_t;
        }
    }

    /**
     * 乘法
     * @param $data
     * @param $t
     * @return mixed
     */
    private static function times($data, $t)
    {
        return $data * $t;
    }

    private static function excelTime($time)
    {
        return round(($time - 25569) * 86400 - 28800);
    }

    private static function captchaDecode($data, $type = '')
    {
        return LibCaptcha::captchaDecode($data, $type);
    }

    /**
     * 私钥加密
     * @param $str
     * @param $keyPath
     * @return string
     */
    private static function pemSign($str, $keyPath)
    {
        if (empty($keyPath) || !is_file($keyPath)) {
            return '';
        }
        $privateKey = file_get_contents($keyPath);
        $pKeyId = openssl_get_privatekey($privateKey);

        openssl_sign($str, $signMsg, $pKeyId, OPENSSL_ALGO_SHA1);

        openssl_free_key($pKeyId);

        $signMsg = base64_encode($signMsg);

        return $signMsg;
    }

    /**
     * 检查字符串是否是UTF8状态
     * @param $str
     * @return int
     */
    public static function isUtf8($str)
    {
        return preg_match('%^(?:
		 [\x09\x0A\x0D\x20-\x7E]            # ASCII
	   | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
	   |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
	   | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
	   |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
	   |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
	   | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
	   |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
        )*$%xs', $str);
    }

    public static function forceUtf8($org)
    {
        if (!is_array($org)) {
            if (strlen($org) > 250) {
                return $org;
            }

            return self::isUtf8($org) ? $org : iconv('GBK', 'UTF-8', $org);
        } else {
            foreach ($org as $k => $v) {
                $org[$k] = self::forceUtf8($v);
            }

            return $org;
        }
    }


    /**
     * 中英文混杂的时候分割字符串
     * @param $str
     * @return array
     */
    public static function strSplit($str)
    {
        $str = iconv("UTF-8", 'GBK', $str);
        $strLen = strlen($str);
        $array = array();
        for ($j = 0; $j < $strLen; $j++) {
            if (ord($str[$j]) < 127) {
                $array[] = iconv('GBK', "UTF-8", $str[$j]);
                continue;
            } else {
                if (ord($str[$j + 1]) > 127) {
                    $array[] = iconv('GBK', "UTF-8", $str[$j] . $str[$j + 1]);
                    $j++;
                    continue;
                } else {
                    $array[] = iconv('GBK', "UTF-8", $str[$j]);
                    continue;
                }
            }
        }
        return $array;
    }


    /**
     * 生成随机字符串
     * @param int $n 长度
     * @param string $f (大写字母，小写字母，数字)要允许的在当前位写1 否则写0
     * @param array $d 排除的元素
     * @param array $r 排除的元素的替换方案
     * @return string
     */
    public static function randStr($n, $f = "111", $d = array(), $r = array(65, 72))
    {
        $x = array_diff(str_split($f), array('0'));

        $_t = array(
            array(65, 90),
            array(97, 122),
            array(48, 57)
        );

        $code = '';
        for ($i = 0; $i < $n; $i++) {
            $_x = array_rand($x, 1);
            $_y = mt_rand($_t[$_x][0], $_t[$_x][1]);
            if ($d) {
                if (in_array($_y, $d)) {
                    $_y = mt_rand($r[0], $r[1]);
                }
            }
            $code .= chr($_y);
        }

        return $code;
    }

    public static function print_r($data)
    {
        header("Content-type: text/html; charset=utf-8");
        echo "<pre>";
        print_r($data);
        echo "</pre>";
    }
}
